package com.springsummer.information.green.io;

import java.io.File;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

public class NormalScanService implements ScanService {

    /**
     * @param packageName
     * @return Collection<String> 扫描指定包下的classNames
     */
    @Override
    public Collection<String> scan(String packageName) {
        try {

            List<String> classNameList = scanClassFiles(packageName);
            return classNameList;

        } catch (Exception ex) {
            ex.printStackTrace();
            return Collections.emptyList();
        }
    }

    @Override
    public Collection<String> scanPackages(String... packageName) {
        Collection<String> collectionDatas = new ArrayList<>(256);
        for (String packagename : packageName) {
            Collection<String> datas = this.scan(packagename);
            collectionDatas.addAll(datas);
        }
        return collectionDatas;
    }

    public List<String> scanClassFiles(String packageName) throws Exception {
        List<String> classNames = new ArrayList<>(256);

        //com.spring.campusall.hello.service
        //替换.为package目录,例如，Classpath中搜索的文件org/example/Hello.class符合包名org.example
        String pathName = packageName.replaceAll("\\.", "/");
        System.out.println("scanClassFiles packageName = " + packageName + " dirName = " + pathName);

        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        Enumeration<URL> enumeration = classLoader.getResources(pathName);
        while (enumeration.hasMoreElements()) {
            URL elementUrl = enumeration.nextElement();
            String protocol = elementUrl.getProtocol();
            if (protocol.equalsIgnoreCase("file")) {
                //扫描目录和文件
                // 处理文件目录
                File directory = new File(elementUrl.toURI());
                scanDirectory(directory, packageName, classNames);

            } else if (protocol.equalsIgnoreCase("jar")) {
                scanJarFiles(elementUrl, pathName, classNames);
            }

        }

        return classNames;
    }

    private static void scanJarFiles(URL elementUrl, String pathName, List<String> classNames) throws IOException {
        // 处理jar包
        JarURLConnection jarConn = (JarURLConnection) elementUrl.openConnection();
        JarFile jarFile = jarConn.getJarFile();
        Enumeration<JarEntry> entries = jarFile.entries();
        while (entries.hasMoreElements()) {
            JarEntry entry = entries.nextElement();
            String entryName = entry.getName();
            if (entryName.startsWith(pathName) && entryName.endsWith(".class")) {
                String className = entryName.replace('/', '.').substring(0, entryName.length() - 6);
                classNames.add(className);
            }
        }
    }

    public void scanDirectory(File directory, String packageName, List<String> classNames) throws Exception {
        File[] files = directory.listFiles();
        if (files == null) return;
        for (File file : files) {
            if (file.isDirectory()) {
                scanDirectory(file, packageName + "." + file.getName(), classNames);
            } else if (file.getName().endsWith(".class")) {
                String className = packageName + '.' + file.getName().substring(0, file.getName().length() - 6);
                classNames.add(className);
            }
        }
    }

}
